001 /*
002 * Copyright 2005-2006 Stephen McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.station.server;
020
021 import java.io.IOException;
022 import java.io.InputStream;
023 import java.io.ObjectInputStream;
024 import java.io.BufferedInputStream;
025 import java.net.Socket;
026 import java.net.ServerSocket;
027 import java.net.SocketException;
028 import java.util.logging.Logger;
029 import java.util.logging.LogRecord;
030
031 import net.dpml.depot.LogStatement;
032
033 import net.dpml.lang.PID;
034
035 /**
036 * The LoggingServer is a remote service that handles the aggregation of
037 * log records from multiple jvm processes.
038 *
039 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
040 * @version 1.0.0
041 */
042 public class LoggingServer implements Runnable
043 {
044 private static final PID PROCESS = new PID();
045
046 private final ServerSocket m_server;
047
048 private int m_count = 0;
049
050 /**
051 * Creation of a new logging service instance.
052 * @param port the log server port
053 * @exception IOException if an IO exception occurs
054 */
055 public LoggingServer( int port ) throws IOException
056 {
057 m_server = new ServerSocket( port );
058 }
059
060 /**
061 * Runnable implementation.
062 */
063 public void run()
064 {
065 while( true )
066 {
067 try
068 {
069 Socket socket = m_server.accept();
070 RequestHandler handler = new RequestHandler( socket );
071 Thread thread = new Thread( handler );
072 thread.start();
073 }
074 catch( Throwable e )
075 {
076 e.printStackTrace();
077 m_count++;
078 }
079 }
080 }
081
082 int getErrorCount()
083 {
084 return m_count;
085 }
086
087 /**
088 * Internal utility class to handle a client connection.
089 */
090 final class RequestHandler implements Runnable
091 {
092 private final Socket m_socket;
093
094 /**
095 * Creation of a new request handler.
096 * @param socket the socket
097 */
098 private RequestHandler( Socket socket )
099 {
100 m_socket = socket;
101 }
102
103 /**
104 * Run the process.
105 */
106 public void run()
107 {
108 try
109 {
110 InputStream input = m_socket.getInputStream();
111 BufferedInputStream buffer = new BufferedInputStream( input );
112 ObjectInputStream ois = new ObjectInputStream( buffer );
113 while( true )
114 {
115 Object object = ois.readObject();
116 if( object instanceof LogStatement )
117 {
118 LogStatement statement = (LogStatement) object;
119 PID pid = statement.getPID();
120 if( !PROCESS.equals( pid ) )
121 {
122 int id = pid.getValue();
123 LogRecord record = statement.getLogRecord();
124 String raw = record.getMessage();
125 String message = "$[" + id + "] " + raw;
126 record.setMessage( message );
127 Logger logger = getNamedLogger( record );
128 logger.log( record );
129 }
130 }
131 }
132 //System.out.println( "## DONE" );
133 //input.close();
134 //m_socket.close();
135 }
136 catch( ClassNotFoundException e )
137 {
138 e.printStackTrace();
139 }
140 catch( SocketException ioe )
141 {
142 // ignore
143 }
144 catch( IOException ioe )
145 {
146 ioe.printStackTrace();
147 }
148 }
149
150 private Logger getNamedLogger( LogRecord record )
151 {
152 String name = record.getLoggerName();
153 if( null != name )
154 {
155 return Logger.getLogger( name );
156 }
157 else
158 {
159 return Logger.getAnonymousLogger();
160 }
161 }
162 }
163
164 }
165